package com.learn.sunday.auth.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.learn.sunday.auth.bean.*;
import com.learn.sunday.auth.constants.ServerLevelTypeEnum;
import com.learn.sunday.auth.dao.ViidServerDao;
import com.learn.sunday.auth.service.SystemService;
import com.learn.sunday.auth.service.UserService;
import com.learn.sunday.common.service.utils.DigestUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Base64;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class SystemServiceImpl implements SystemService {


    private static final int nonceValidSeconds = 300;

    @Value("${digest.device.key:2222222222222}")
    private String key;

    @Value("${digest.device.realm:vvcdsa}")
    private String realmName;

    @Value("${digest.device.valid.time:90}")
    private Integer deviceValidTime;


    @Autowired
    private ViidServerDao viidServerDao;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Override
    public void doRegister(RegisterObject registerObject,HttpServletRequest request, HttpServletResponse response)  {
        log.info("注册请求信息:{}",JSON.toJSONString(registerObject));
        String deviceId = registerObject.getDeviceId();
        JSONObject json = new JSONObject();

        if (StringUtils.isBlank(deviceId)) {
            json.put("error","DeviceId is not present!");
        } else {
            ViidServer viidServer = new ViidServer();
            viidServer.setDeviceId(deviceId);
            viidServer.setType(ServerLevelTypeEnum.UPPER.getValue());
            ViidServer viidServer1 = viidServerDao.selectOne(viidServer);
            if (viidServer1 == null) {
                json.put("error","DeviceId is not present2!");
            }

        }
        if (!json.isEmpty()) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED,json.toJSONString());
            return;
        }


        String requestId = request.getRemoteHost() + ":" + deviceId;
        log.info("keyu === {}",requestId);
        final String authorization = request.getHeader("authorization");
        if (StringUtils.isBlank(authorization)) {

            log.info("It is {} first auth!...");
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            long expiryTime = System.currentTimeMillis() + nonceValidSeconds * 1000;
            String signatureValue = DigestUtils.md5Hex(expiryTime + ":" + key);
            String nonceValue = expiryTime + ":" + signatureValue;
            String nonceValueBase64 = new String(Base64.getEncoder().encode(nonceValue.getBytes()));
            String authenticateHeader = "Digest realm=\"" + realmName + "\", "
                    + "qop=\"auth\", nonce=\"" + nonceValueBase64 + "\"";
            log.info("auth---{}",authenticateHeader);
            response.addHeader("WWW-Authenticate", authenticateHeader);
        } else {

            DigestBean digestBean = new DigestBean(authorization);
            boolean b = digestBean.validateAndDecode(key, realmName);
            if (!b) {
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED,"认证信息错误! ");
                return;
            }
            String username = digestBean.getUsername();
            log.info("二次认证信息:{}", JSON.toJSONString(digestBean));
            redisTemplate.opsForValue().set(deviceId,username,300L,TimeUnit.SECONDS);
        }

    }

    @Override
    public ResponseStatus doKeepalive(KeepAlive keepAlive, HttpServletRequest request, HttpServletResponse response) {
        if (redisTemplate.opsForValue().get(keepAlive.getDeviceId()) != null) {
            redisTemplate.opsForValue().set(keepAlive.getDeviceId(),
                    redisTemplate.opsForValue().get(keepAlive.getDeviceId()),300L,TimeUnit.SECONDS);
            return ResponseStatus.successResponse(request).setId(keepAlive.getDeviceId());
        } else {
            return ResponseStatus.failedResponse(request).setId(keepAlive.getDeviceId()).setStatusString("设备未注册或者注册已过期");
        }
    }
}
